package web.suzy.oj.dao.user.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.LogoutAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import web.suzy.oj.dao.user.SysUserRoleEntityService;
import web.suzy.oj.mapper.SysUserRoleMapper;
import web.suzy.oj.pojo.entity.user.SysRole;
import web.suzy.oj.pojo.entity.user.SysUserRole;
import web.suzy.oj.pojo.vo.SysUserRoleVO;
import web.suzy.oj.shiro.AccountProfile;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * YangSuzy 软件工作室
 * 类名: SysUserRoleEntityServiceImpl
 * 描述: 用户角色表实体 dao层服务实现类
 * 功能: ---- 待定 -----
 *
 * @author YangSuzy
 * Date: 2022/11/9 13:32
 */
@Service
public class SysUserRoleEntityServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements SysUserRoleEntityService {

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private RedisSessionDAO redisSessionDAO;

    /**
     * 方法名: getUserRoles
     * 描述: 根据用户 UID或用户名获取用户信息以及其对应的角色
     *
     * @param uid      用户 UID
     * @param username 用户名
     * @return web.suzy.oj.pojo.vo.SysUserRoleVO
     * @date 2022/11/9 13:29
     * @auther YangSuzy
     **/
    @Override
    public SysUserRoleVO getUserRoles(String uid, String username) {
        return sysUserRoleMapper.getUserRoles(uid, username);
    }

    /**
     * 方法名: getRolesByUid
     * 描述: 根据用户 UID获取角色列表
     *
     * @param uid 用户 UID
     * @return java.util.List<web.suzy.oj.pojo.entity.user.SysRole>
     * @date 2022/11/9 13:34
     * @auther YangSuzy
     **/
    @Override
    public List<SysRole> getRolesByUid(String uid) {
        return sysUserRoleMapper.getRolesByUid(uid);
    }

    /**
     * 方法名: getUserList
     * 描述: 根据关键字分页模糊查询获取用户信息列表
     *
     * @param limit       每页显示数量
     * @param currentPage 当前页
     * @param keyword     关键字
     * @param onlyAdmin   true-只查管理员 false-全查
     * @return com.baomidou.mybatisplus.core.metadata.IPage<web.suzy.oj.pojo.vo.SysUserRoleVO>
     * @date 2022/11/9 13:34
     * @auther YangSuzy
     **/
    @Override
    public IPage<SysUserRoleVO> getUserList(int limit, int currentPage, String keyword, Boolean onlyAdmin) {
        //新建分页对象
        Page<SysUserRoleVO> page = new Page<>(currentPage, limit);
        if (onlyAdmin) {
            return sysUserRoleMapper.getAdminUserList(page, limit, currentPage, keyword);
        }
        return sysUserRoleMapper.getUserList(page, limit, currentPage, keyword);
    }

    /**
     * 方法名: deleteCache
     * 描述: 删除用户登录会话缓存
     *
     * @param uid             用户ID
     * @param isRemoveSession 是否强行删除登录会话
     * @return void
     * @date 2022/11/27 18:10
     * @auther YangSuzy
     **/
    @Override
    public void deleteCache(String uid, boolean isRemoveSession) {
        //从缓存中获取登录Session
        Collection<Session> sessions = redisSessionDAO.getActiveSessions();
        for (Session sessionInfo : sessions) {
            //遍历Session,找到该用户名称对应的Session
            Object attribute = sessionInfo.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            if (attribute == null) {
                continue;
            }
            AccountProfile accountProfile = (AccountProfile) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
            if (accountProfile == null) {
                continue;
            }
            //如果该session是指定uid用户的则直接删除缓存
            if (Objects.equals(accountProfile.getUid(), uid)) {
                deleteSession(isRemoveSession, sessionInfo, attribute);
            }
        }
    }

    /**
     * 方法名: deleteSession
     * 描述: 删除用户登录会话
     *
     * @param isRemoveSession 是否强行移除会话
     * @param session         用户登录会话
     * @param attribute       用户登录属性
     * @return void
     * @date 2022/11/27 18:13
     * @auther YangSuzy
     **/
    private void deleteSession(boolean isRemoveSession, Session session, Object attribute) {
        //删除session会强制退出，主要用于禁用用户或角色时强制用户退出
        if (isRemoveSession) {
            redisSessionDAO.delete(session);
        }
        //删除Cache，在访问受限接口时会重新授权
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        Authenticator authc = securityManager.getAuthenticator();
        ((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
    }

    private final static List<String> CHINESE_ROLE = Arrays.asList("超级管理员", "普通管理员",
            "普通用户(默认)", "普通用户(禁止提交)", "普通用户(禁止发讨论)", "普通用户(禁言)", "普通用户(禁止提交&禁止发讨论)",
            "用户(禁止提交&禁言)", "题目管理员");

    private final static List<String> ENGLISH_ROLE = Arrays.asList("Super Administrator", "General Administrator",
            "Normal User(Default)", "Normal User(No Submission)", "Normal User(No Discussion)", "Normal User(Forbidden Words)",
            "Normal User(No Submission & No Discussion)",
            "Normal User(No Submission & Forbidden Words)", "Problem Administrator");

    /**
     * 方法名: getAuthChangeContent
     * 描述: 获取权限修改文本发送给用户
     *
     * @param oldType 旧权限
     * @param newType 新权限
     * @return java.lang.String
     * @date 2022/11/27 18:15
     * @auther YangSuzy
     **/
    @Override
    public String getAuthChangeContent(int oldType, int newType) {
        return "您好，您的权限产生了变更，由【" +
                CHINESE_ROLE.get(oldType - 1000) +
                "】变更为【" +
                CHINESE_ROLE.get(newType - 1000) +
                "】。部分权限可能与之前有所不同，请您注意！" +
                "\n\n" +
                "Hello, your permission has been changed from 【" +
                ENGLISH_ROLE.get(oldType - 1000) +
                "】 to 【" +
                ENGLISH_ROLE.get(newType - 1000) +
                "】. Some permissions may be different from before. Please note!";
    }

}
